package com.jessechanrui.template.projectcase.config.advice;

import com.jessechanrui.template.projectcase.common.base.BaseException;
import com.jessechanrui.template.projectcase.common.base.ResultResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;

/**
 * @author chenrui
 * @date 2024/2/29
 */
@RestControllerAdvice
@Slf4j
public class CommonExceptionHandler {

    /**
     * 方法参数校验异常
     * @param ex
     * @return
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public ResultResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        BindingResult bindingResult = ex.getBindingResult();
        StringBuilder sb = new StringBuilder("校验失败，");
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            sb.append(fieldError.getField()).append("：").append(fieldError.getDefaultMessage()).append("； ");
        }
        String msg = sb.toString();
        ResultResponse respMessage = ResultResponse.builder().build();
        respMessage.setMessage(msg);
        respMessage.setCode(HttpServletResponse.SC_BAD_REQUEST);
        return respMessage;
    }

    /**
     * 参数约束异常
     * @param e
     * @return
     */
    @ExceptionHandler({ConstraintViolationException.class})
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public ResultResponse handleConstraintViolationException(ConstraintViolationException e) {
        ResultResponse respMessage = ResultResponse.builder().build();
        log.error(String.valueOf(e));
        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
        StringBuilder builder = new StringBuilder();
        for (ConstraintViolation violation : violations) {
            builder.append(violation.getMessage());
            break;
        }
        respMessage.setMessage(builder.toString());
        respMessage.setCode(HttpServletResponse.SC_BAD_REQUEST);
        return respMessage;
    }

    /**
     * 业务异常
     * @param e
     * @return
     */
    @ExceptionHandler({BaseException.class})
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public ResultResponse handleCBaseException(BaseException e) {
        ResultResponse respMessage = ResultResponse.builder().build();
        respMessage.setCode(e.getCode());
        respMessage.setMessage(e.getMessage());
        return respMessage;
    }

    /**
     * 其他异常处理
     * @param request
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public ResultResponse defaultErrorHandler(HttpServletRequest request, Exception e) {
        log.error(e.getMessage(), e);
        ResultResponse respMessage = ResultResponse.builder().build();
        respMessage.setMessage(e.getMessage());
        if (e instanceof NoHandlerFoundException) {
            respMessage.setCode(HttpServletResponse.SC_NOT_FOUND);
        }  else {
            respMessage.setCode(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
        return respMessage;
    }
}

